import React, { memo, useCallback, useEffect, useMemo, useState } from 'react';
import { message, Modal, Popconfirm } from 'antd';
import Dragger from 'antd/lib/upload/Dragger';
import { InboxOutlined } from '@ant-design/icons';
import style from './btnupload.module.scss';
import { UploadChangeParam, UploadProps } from 'antd/lib/upload';
import { PACKAGE_NAME } from './../../app/automatic/package';
import { UploadFile, RcFile } from 'antd/lib/upload/interface';
import preDeletePrompt from '../button/preDeletePrompt';
import Button from './../button/Button';
import MIME from '@library/components/fileUpload/mime';
import { DEFAULT_ACCEPT } from '@library/components/fileUpload/FileUpload';
import Icon from './../icon/Icon';
const UPLOAD_URL = '/bk/uploadIpfs/';
const DEFAULT_GET_FILE_URL = '/bk/getFile/';
const t = window.$app.t;
const officeSuffix = ['pdf', 'doc', 'docx', 'xlsx'];
const imgSuffix = ['jpeg', 'gif', 'jpg', 'png', 'bmp', 'ico'];
function handleUrl(url: string | undefined, downloadUrl?: string) {
  let urlDeal;
  if (!url || url.includes('http') || url.includes(DEFAULT_GET_FILE_URL)) {
    urlDeal = url;
  } else {
    urlDeal = (downloadUrl || DEFAULT_GET_FILE_URL) + url;
  };

  if (urlDeal) {
    urlDeal = urlDeal + (urlDeal.includes('m=dev') ? '' : urlDeal.includes('?') ? '&m=dev' : '?m=dev');
  }

  return urlDeal;
}

interface IPropsUpload extends UploadProps {
  disabled?: boolean;
  onlyShowList?: boolean;
  fileSize?: number;  // M
  onChange: (info: UploadChangeParam<UploadFile<any>>) => void;
  onDelete: (id: string) => void;
  beforeUpload?: (file: RcFile, FileList: RcFile[]) => void;
  targetNode?: React.ReactNode;
  downloadUrl?: string;
  only?: boolean;
}

export const onHandleViewUrl = (attachPath?: string) => {
  if (!attachPath) return '';
  if (attachPath.startsWith('http')) return window.open(attachPath, '_blank');

  const fileName = attachPath?.split('?')?.[0];
  const suffix = fileName?.split('.').pop()?.toLocaleLowerCase();

  if (suffix) {
    if (imgSuffix.includes(suffix)) {
      const newwindow = window.open(window.location.origin) as any;
      newwindow?.document?.write(`
        <html>
          <title>${t('view')}</title>
          <body style="display: flex; justify-content: center; align-items: center">
            <img src=${encodeURI(handleUrl(attachPath)!)} />
          </body>
        </html>
      `);
    } else if (officeSuffix.includes(suffix) && !attachPath.includes('mode=1')) {
      window.open('/bk/previewFile/' + attachPath.replace('/bk/getFile/', ''));
    } else {
      window.open(handleUrl(attachPath));
    }
  }
};


const Upload = (props: IPropsUpload) => {

  const { disabled, fileSize, multiple, onChange, beforeUpload, onlyShowList, onDelete, targetNode, downloadUrl, only } = props;

  const [fileListArr, setFileListArr] = useState<any[]>([]);
  const [activeIndex, setActiveIndex] = useState<number | undefined>();

  useEffect(() => {
    const list = props.fileList || [];
    list.forEach((item: any) => {
      if (!item.uid) item.uid = item.id;
      if (!item.name) item.name = item.fileName;
      item.url = handleUrl(item.attachPath || item.response?.filename, downloadUrl);
    });
    setFileListArr(list || []);
  }, [props.fileList, downloadUrl]);

  const [visible, setVisible] = useState(false);

  const showUpload = useCallback(() => setVisible(true), []);

  const onCancel = useCallback(() => {
    setVisible(false);
    setActiveIndex(undefined);
  }, []);

  const mimeTypes = useMemo(() => {
    const accept = (props.accept || DEFAULT_ACCEPT).split(',');
    return accept.map(item => MIME[item]).flat();
  }, [props.accept]);

  const _beforeUpload = useCallback(
    (file, fileList) => {
      return new Promise((resolve) => {
        if (only && fileListArr.length >= 1) {
          message.warning(t('uploadTip3'));
          return false;
        }

        const SIZE = fileSize || 20;
        if (file && file.size > SIZE * 1024 * 1024) {
          message.error(`单个附件超出规定尺寸${SIZE}M`);
          return false;
        }

        if (file.type && !mimeTypes.includes(file.type)) {
          message.warning(t('uploadTip4'));
          setFileListArr(fileList.filter((item: any) => item.uid !== file.uid));
          return false;
        }

        return resolve(true);
      });
    },
    [fileSize, only, fileListArr]
  );

  const onFileChange = useCallback((f: UploadChangeParam) => {
    setFileListArr([...f.fileList]);
    if (f.file?.status === "done") onChange(f);
  }, [onChange]);

  const deleteFile = useCallback((item: any) => {
    setActiveIndex(undefined);
    if (item.id) {
      onDelete?.(item);

      setFileListArr((prev: any) => {
        const list = prev.filter((ele: any) => {
          if (ele.id) {
            ele.url = handleUrl(ele.attachPath);
          }
          return ele.id !== item.id || !ele.id;
        });
        return [...list];
      });
      return true;
    } else {
      onDelete?.(item);

      setFileListArr((prev: any) => {
        const list = prev.filter((ele: any) => {
          if (ele.id && item.id) return ele.id !== item.id;
          if (ele.uid && item.uid) return ele.uid !== item.uid;
          if (ele.url && item.url) return ele.url !== item.url;
          return ele?.response?.url !== item?.response?.url;
        });
        return [...list];
      });
      return true;
    }
  }, [onDelete]);


  const showBtnFileList = useMemo(() => {
    return (
      <ul className={style.fileListStyle}>
        {fileListArr.map((ele, index) => {
          return (
            <li key={ele.id || index} className={activeIndex === index ? style.active : undefined}>
              <Icon className={style.linkIcon} icon="&#xe629;" />
              <a
                className={style.oneEllipsis}
                onClick={() => onHandleViewUrl(ele.attachPath || ele.response?.filename || ele.url)}
                href="javascript:;"
              >
                {ele.name || ele.fileName}
              </a>
              <Icon
                className={style.forbid}
                icon="&#xe62c;"
                onClick={() => {
                  window.open(handleUrl(ele.attachPath || ele.response?.filename || ele.url));
                }}
              />
              {!disabled && (
                <Popconfirm
                  destroyTooltipOnHide
                  title={t('preDeleteTip')}
                  onConfirm={() => deleteFile(ele)}
                  onVisibleChange={(e) => {
                    if (!e) setActiveIndex(undefined);
                  }}
                >
                  <Icon onClick={() => setActiveIndex(index)} className={style.forbid} icon="&#xe66d;" />
                </Popconfirm>
              )}
            </li>
          );
        })}
      </ul>
    );
  }, [fileListArr, deleteFile, activeIndex]);

  return (
    <>
      {
        targetNode
          ? <div onClick={showUpload}>{targetNode}</div>
          : <div className={style.operateBtnStyle}>
            <Button type="default" className={style.uploadBtn} disabled={disabled} onClick={showUpload}>附件上传</Button>
            {disabled ? null : <span className={style.totalSizes} onClick={showUpload}>共{fileListArr?.length}个附件</span>}

          </div>
      }
      <Modal title={t('attachUpload')} visible={visible} onCancel={onCancel} footer={null}>
        {onlyShowList ? (
          <ul className={style.fileListStyle}>{showBtnFileList}</ul>
        ) :
          <>
            <Dragger
              {...props}
              showUploadList={false}
              onChange={onFileChange}
              onRemove={deleteFile}
              fileList={fileListArr}
              beforeUpload={beforeUpload || _beforeUpload}
              action={(props.action || (UPLOAD_URL + PACKAGE_NAME)) + '?m=dev'}
              multiple={typeof multiple === "boolean" ? multiple : true}
              accept={props.accept || DEFAULT_ACCEPT}
            >
              <p className="ant-upload-drag-icon">
                <InboxOutlined />
              </p>
              <p className="ant-upload-text">{t('uploadTip1')}</p>
              <p className="ant-upload-hint">{t('uploadTip2')}{fileSize || 20}M</p>
            </Dragger>
            {showBtnFileList}
          </>
        }
      </Modal>
    </>
  );
};

function equal(prevProps: IPropsUpload, nextProps: IPropsUpload) {
  return prevProps.fileList === nextProps.fileList
    && prevProps.disabled === nextProps.disabled
    && prevProps.onChange === nextProps.onChange
    && prevProps.onDelete === nextProps.onDelete;
}

export default memo(Upload, equal);
